package com.kingmed.kmss.admin.modules.sys.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kingmed.kmss.admin.modules.sys.mapper.SysOpenRelationMapper;
import com.kingmed.kmss.admin.modules.sys.model.SysOpenGroup;
import com.kingmed.kmss.admin.modules.sys.model.SysOpenRelation;
import com.kingmed.kmss.admin.modules.sys.model.SysOpenUrl;
import com.kingmed.kmss.admin.modules.sys.service.ISysOpenGroupService;
import com.kingmed.kmss.admin.modules.sys.service.ISysOpenRelationService;
import com.kingmed.kmss.admin.modules.sys.service.ISysOpenUrlService;
import com.kingmed.kmss.admin.modules.sys.service.helper.OpenRelationCacheHelper;
import com.kingmed.kmss.common.constant.common.CommonConstants;
import com.kingmed.kmss.common.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 对外授权接口关系Service业务层处理
 *
 * @author Sys
 * @date 2022-12-16
 */
@Slf4j
@Service
public class SysOpenRelationServiceImpl extends ServiceImpl<SysOpenRelationMapper, SysOpenRelation> implements ISysOpenRelationService
{

    @Autowired
    @Lazy
    private ISysOpenUrlService openUrlService;
    @Autowired
    @Lazy
    private ISysOpenGroupService openGroupService;
    @Autowired
    private SysOpenRelationMapper sysOpenRelationMapper;
    @Autowired
    private OpenRelationCacheHelper openRelationCacheHelper;

    /**
     * 项目启动时，初始化参数到缓存
     */
    @PostConstruct
    public void init()
    {
        loadingCache();
    }

    /**
     * 加载对外接口redis缓存
     */
    @Override
    public void loadingCache() {

        log.info(" === 加载对外接口redis缓存开始 ===");

        // 重新查找数据加载
        List<SysOpenRelation> list = this.list();
        if (CollUtil.isEmpty(list)){
            // 清除缓存
            openRelationCacheHelper.remove();
            return;
        }

        List<Long> urlIds = list.stream().map(SysOpenRelation::getUrlId).distinct().collect(Collectors.toList());
        List<Long> groupIds = list.stream().map(SysOpenRelation::getGroupId).distinct().collect(Collectors.toList());

        // 获取现有的关系
        Map<Long, SysOpenUrl> openUrlMap = openUrlService.listByIdsReturnMap(urlIds);
        Map<Long, SysOpenGroup> openGroupMap = openGroupService.listByIdsReturnMap(groupIds);
        // 将关系分组
        Map<Long, List<SysOpenRelation>> listMap = list.stream().collect(Collectors.groupingBy(p -> p.getGroupId()));

        // 组装缓存
        Map<String, HashMap<String, String>> newMap = openRelationCacheHelper.initBigMap(openUrlMap, openGroupMap, listMap);
        openRelationCacheHelper.putMap(newMap);

        log.info(" === 加载对外接口redis缓存结束，{} ===", JSONUtil.toJsonStr(newMap));

    }


    /**
     * 查询对外授权接口关系
     *
     * @param id 对外授权接口关系主键
     * @return 对外授权接口关系
     */
    @Override
    public SysOpenRelation selectSysOpenRelationById(String id)
    {
        return getById(id);
    }

    /**
     * 查询对外授权接口关系列表
     *
     * @param sysOpenRelation 对外授权接口关系
     * @return 对外授权接口关系
     */
    @Override
    public List<SysOpenRelation> selectSysOpenRelationList(SysOpenRelation sysOpenRelation)
    {
        return sysOpenRelationMapper.selectSysOpenRelationList(sysOpenRelation);
    }

    /**
     * 分页
     * @param sysOpenRelation
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public Page<SysOpenRelation> list(SysOpenRelation sysOpenRelation, Integer pageNum, Integer pageSize) {
        Page<SysOpenRelation> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<SysOpenRelation> wrapper = this.initBaseQueryWrapper(sysOpenRelation);
        return page(page, wrapper);
    }

    /**
     * 新增对外授权接口关系
     *
     * @param sysOpenRelation 对外授权接口关系
     * @return 结果
     */
    @Override
    public boolean insertSysOpenRelation(SysOpenRelation sysOpenRelation)
    {
        checkIsExist(sysOpenRelation, true);
        if (save(sysOpenRelation)){
            // 重新清理缓存
            this.loadingCache();
            return true;
        }
        return false;
    }

    /**
     * 批量新增对外授权接口关系
     *
     * @param sysOpenRelationList 对外授权接口关系集合
     * @return 结果
     */
    @Override
    public boolean saveBatchByList(List<SysOpenRelation> sysOpenRelationList) {
        if (CollUtil.isNotEmpty(sysOpenRelationList)){
            saveBatch(sysOpenRelationList);
            this.loadingCache();
            return true;
        }
        return false;
    }

    /**
     * 修改对外授权接口关系
     *
     * @param sysOpenRelation 对外授权接口关系
     * @return 结果
     */
    @Override
    public boolean updateSysOpenRelation(SysOpenRelation sysOpenRelation)
    {
        checkIsExist(sysOpenRelation, false);
        if (updateById(sysOpenRelation)){
            // 重新清理缓存
            this.loadingCache();
            return true;
        }
        return false;
    }

    /**
     * 批量删除对外授权接口关系
     *
     * @param ids 需要删除的对外授权接口关系主键
     * @return 结果
     */
    @Override
    public boolean deleteSysOpenRelationByIds(String[] ids)
    {
        if (ids == null || ids.length == 0){
            return false;
        }
        if (removeByIds(Arrays.asList(ids))){
            // 重新清理缓存
            this.loadingCache();
            return true;
        }
        return false;
    }

    /**
     * 删除对外授权接口关系信息
     *
     * @param id 对外授权接口关系主键
     * @return 结果
     */
    @Override
    public boolean deleteSysOpenRelationById(String id)
    {
        if (StringUtils.isBlank(id)){
            return false;
        }
        if (removeById(id)){
            // 重新清理缓存
            this.loadingCache();
            return true;
        }
        return false;
    }

    /**
     * 删除关联关系
     * @param groupId
     */
    @Override
    public void deleteByGroupId(String groupId) {
        if (StringUtils.isNotBlank(groupId)) {
            LambdaQueryWrapper<SysOpenRelation> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SysOpenRelation::getGroupId, groupId);
            if(this.remove(wrapper)){
                // 重新清理缓存
                this.loadingCache();
            }
        }
    }

    /**
     * 删除关联关系
     * @param groupIds
     */
    @Override
    public void deleteByGroupId(List<String> groupIds) {
        if (CollUtil.isNotEmpty(groupIds)) {
            LambdaQueryWrapper<SysOpenRelation> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(SysOpenRelation::getGroupId, groupIds);
            if(this.remove(wrapper)){
                // 重新清理缓存
                this.loadingCache();
            }
        }
    }

    /**
     * 删除关联关系
     * @param urlId
     */
    @Override
    public void deleteByUrlId(String urlId) {
        if (StringUtils.isNotBlank(urlId)) {
            LambdaQueryWrapper<SysOpenRelation> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SysOpenRelation::getGroupId, urlId);
            if(this.remove(wrapper)){
                // 重新清理缓存
                this.loadingCache();
            }
        }
    }

    /**
     * 删除关联关系
     * @param urlIds
     */
    @Override
    public void deleteByUrlIds(List<String> urlIds) {
        if (CollUtil.isNotEmpty(urlIds)) {
            LambdaQueryWrapper<SysOpenRelation> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(SysOpenRelation::getUrlId, urlIds);
            if(this.remove(wrapper)){
                // 重新清理缓存
                this.loadingCache();
            }
        }
    }

    /**
   * 根据主键集合获取数据
   * @return
   */
    @Override
    public Map<Long, SysOpenRelation> listByIdsReturnMap(List<String> ids) {
        List<SysOpenRelation> list = listByIds(ids);
        if (CollectionUtils.isEmpty(list)){
            return new HashMap<>();
        }
        return list.stream().collect(Collectors.toMap(p -> p.getId(), p -> p ));
    }


    /**
    * 检查是否存在
    * @return
    */
    private boolean checkIsExist(SysOpenRelation sysOpenRelation, boolean isAdd){
        LambdaQueryWrapper<SysOpenRelation> wrapper = null;
        // 修改需要把主键设置为null
        SysOpenRelation updateQuery = new SysOpenRelation();
        updateQuery.setGroupId(sysOpenRelation.getGroupId());
        updateQuery.setUrlId(sysOpenRelation.getUrlId());
        if (!isAdd) {
            wrapper = initBaseQueryWrapper(updateQuery);
        }else {
            wrapper = initBaseQueryWrapper(sysOpenRelation);
        }
        wrapper.last(CommonConstants.LIMIT_ONE);
        SysOpenRelation sysOpenRelationEntity = getOne(wrapper);
        if (null != sysOpenRelationEntity){
            if ((null !=sysOpenRelation.getId()) || !sysOpenRelationEntity.getId().equals(sysOpenRelation.getId())){
                throw new BusinessException("该信息已存在，请勿重复添加");
            }
        }
        return false;
    }

    /**
    * 初始化实体查询
    * @return
    */
    private LambdaQueryWrapper<SysOpenRelation> initBaseQueryWrapper(SysOpenRelation sysOpenRelation){
        LambdaQueryWrapper<SysOpenRelation> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(null !=sysOpenRelation.getId(), SysOpenRelation::getId, sysOpenRelation.getId());
        wrapper.eq(null != sysOpenRelation.getGroupId(), SysOpenRelation::getGroupId, sysOpenRelation.getGroupId());
        wrapper.eq(null != sysOpenRelation.getUrlId(), SysOpenRelation::getUrlId, sysOpenRelation.getUrlId());
        wrapper.eq(StringUtils.isNotBlank(sysOpenRelation.getCreateBy()), SysOpenRelation::getCreateBy, sysOpenRelation.getCreateBy());
        wrapper.eq(null != sysOpenRelation.getCreateTime(), SysOpenRelation::getCreateTime, sysOpenRelation.getCreateTime());
        wrapper.eq(StringUtils.isNotBlank(sysOpenRelation.getUpdateBy()), SysOpenRelation::getUpdateBy, sysOpenRelation.getUpdateBy());
        wrapper.eq(null != sysOpenRelation.getUpdateTime(), SysOpenRelation::getUpdateTime, sysOpenRelation.getUpdateTime());
        return wrapper;
    }

}
